local modid = 'webber_the_trainer'

-----
local NUM_HORROR_VARIATIONS = 6  -- 恐惧变体数量
local MAX_HORRORS = 4            -- 最大恐惧数量
local HORROR_PERIOD = 1          -- 闪烁周期
local INITIAL_RND_PERIOD = 0.35  -- 初始延迟

-- 回收特效
-- @param fx 特效
-- @param pool 池
local function RecycleHorrorDebuffFX(fx, pool)
	fx:RemoveFromScene()
	table.insert(pool, fx)
end

-- 更新群聚恐惧特效：
-- @param target 目标
-- @param attacker 攻击者
-- @param data 数据
-- @param endtime 结束时间
-- @param first 是否第一次触发
local function OnUpdate_HorrorFuel(target, attacker, data, endtime, first)
    if not (target.components.health and target.components.health:IsDead()) and
        target.components.combat and target.components.combat:CanBeAttacked()
    then
        -- 随机选择效果变体
        local rnd = math.random(math.clamp(NUM_HORROR_VARIATIONS - #data.tasks, 2, NUM_HORROR_VARIATIONS / 2))
        local variation = data.variations[rnd]
        for i = rnd, NUM_HORROR_VARIATIONS - 1 do
            data.variations[i] = data.variations[i + 1]
        end
        data.variations[NUM_HORROR_VARIATIONS] = variation

        -- 获取或创建特效
        local fx
        if #data.pool > 0 then
            fx = table.remove(data.pool)
            fx:ReturnToScene()
        else
            fx = SpawnPrefab("slingshotammo_horrorfuel_debuff_fx")
            fx.pool = data.pool
            fx.onrecyclefn = RecycleHorrorDebuffFX
        end

        -- 设置特效
        fx.entity:SetParent(target.entity)
        fx:Restart(attacker, target, variation, data.pool, first)
    end

    -- 检查是否结束
    if GetTime() >= endtime then
        table.remove(data.tasks, 1):Cancel()
        if #data.tasks <= 0 then
            -- 清理对象池
            for i, v in ipairs(data.pool) do
                v:Remove()
            end
            target._slingshot_horror = nil
        end
    end
end

local function DoHit_HorrorFuel(attacker, target, instant)
    if target and target:IsValid() then

        -- 获取或初始化数据
        local data = target._slingshot_horror
        if data == nil then
            data = { tasks = {}, variations = {}, pool = {} }
            for i = 1, NUM_HORROR_VARIATIONS do
                table.insert(data.variations, math.random(i), i)
            end
            target._slingshot_horror = data
        elseif #data.tasks >= MAX_HORRORS then
            table.remove(data.tasks, 1):Cancel()
        end

        -- 计算持续时间
        local numticks = TUNING.SLINGSHOT_HORROR_TICKS or 5
        local endtime = GetTime() + HORROR_PERIOD * (numticks - 1) - 0.001

        -- 添加任务
        if instant then
            table.insert(data.tasks, target:DoPeriodicTask(HORROR_PERIOD, OnUpdate_HorrorFuel, nil, attacker, data, endtime))
            OnUpdate_HorrorFuel(target, attacker, data, endtime, true)
        else
            local initialdelay = math.random() * 0.35  -- INITIAL_RND_PERIOD = 0.35
            endtime = endtime + initialdelay
            table.insert(data.tasks, target:DoPeriodicTask(HORROR_PERIOD, OnUpdate_HorrorFuel, initialdelay, attacker, data, endtime))
        end
    end
end
---------------------------------------------------------------------------------------------------
-- 上面是前置要用的，因为原版的全是本地函数没法调用所以得复制过来 ---------------------------------------
---------------------------------------------------------------------------------------------------
-- 注意，参数都是实体prefab，而不是string类型的名字
-- @param player 玩家，攻击者，必须有
-- @param target 目标，被攻击者，必须有
-- @param instant 是否立即触发，我还没研究区别，反正true是正常的
-- DoHit_HorrorFuel(player, target, true)
-----
-- 蛛灵之枢(手杖): 隔空取物
for _,v in ipairs({
   "saddle_basic",
   "saddle_war",
   "saddle_race",
}) do
   AddPrefabPostInit(v, function (inst)
        inst:AddOrRemoveTag('webbert_cantbepicked',true)
        if not TheWorld.ismastersim then
            return inst
        end
   end)
end
AddModRPCHandler(modid, "staff_pickitems", function(player)
    if not player:HasTag("playerghost") and player.components.inventory then

        local wp = player.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)
        if wp and wp.prefab == 'staff_arachnidnexus' then
        else
            return -- 不是手杖就不执行
        end
        local x,y,z = player:GetPosition():Get()

        -- local _ents = TheSim:FindEntities(x, 0, z, 2, nil, {"INLIMBO"})
        -- for k,v in pairs(_ents) do
        --     print(v)
        -- end

        local ents = TheSim:FindEntities(x, 0, z, TUNING.MOD_WEBBER_THE_TRAINER.ITEMS.staff_arachnidnexus.skill_2.radius, {"_inventoryitem"}, {"FX", "NOCLICK", "DECOR", "INLIMBO", "trap", "light", "blowdart", "projectile", 'webbert_cantbepicked'})
        for k,v in pairs(ents) do
            if v.components.inventoryitem and v.components.inventoryitem and v.components.inventoryitem.canbepickedup and v.components.inventoryitem.cangoincontainer and not v.components.inventoryitem:IsHeld() and player.components.inventory:CanAcceptCount(v, 1)>0 then
                player.components.inventory:GiveItem(v, nil, v:GetPosition())
            end
        end
    end
end)

-- AddModRPCHandler(modid, "test", function(player)
--     if not player:HasTag("playerghost") then
--         local x,y,z = player.Transform:GetWorldPosition()
--         -- local ents = TheSim:FindEntities(x, y or 0, z,  6, nil, {'player',"INLIMBO"})
--         -- for _,v in pairs(ents) do
--         --     -- v:Remove()
--         --     -- if v.components.combat then
--         --     --     -- DoHit_HorrorFuel(player, v, true)
--         --     --     break
--         --     -- end
--         -- end

--         -- player:AddDebuff('buff_webbert_staff_arachnidnexus_skill_healaccel','buff_webbert_staff_arachnidnexus_skill_healaccel')
--         local fx = SpawnPrefab('particle_webbert_staff_healfx')
--         fx.entity:SetParent(player.entity)
--         -- fx.entity:AddFollower()
--         -- fx.Follower:FollowSymbol(player.GUID, nil, 0, 0, 0)
--     end
-- end)


local data_rt_panel = require('core_webber_the_trainer/data/rt_panel')
AddPlayerPostInit(function(inst)
    inst:DoTaskInTime(0, function()
        if inst == ThePlayer then
            -- TheInput:AddKeyDownHandler(KEY_L, function()
            --     local screen = TheFrontEnd:GetActiveScreen()
            --     local IsHUDActive = screen and screen.name == "HUD"
            --     if inst:IsValid() and IsHUDActive and ThePlayer.HUD and not ThePlayer.HUD:HasInputFocus() then
            --         if inst.prefab == 'webbert' then
            --             SendModRPCToServer(GetModRPC(modid, "test"))
            --         end
            --     end
            -- end)
            -- 手杖快速拾取键
            TheInput:AddKeyDownHandler(SUGAR_webber_the_trainer:getModConfigDataFromTUNING('_staff_key'), function()
                local screen = TheFrontEnd:GetActiveScreen()
                local IsHUDActive = screen and screen.name == "HUD"
                if inst:IsValid() and IsHUDActive and ThePlayer.HUD and not ThePlayer.HUD:HasInputFocus() then
                    SendModRPCToServer(GetModRPC(modid, "staff_pickitems"))
                end
            end)
            -- 不是很通用的通用轮盘
            TheInput:AddKeyDownHandler(SUGAR_webber_the_trainer:getModConfigDataFromTUNING('_rt_panel'), function()
                local screen = TheFrontEnd:GetActiveScreen()
                local IsHUDActive = screen and screen.name == "HUD"
                if inst:IsValid() and IsHUDActive and ThePlayer.HUD and not ThePlayer.HUD:HasInputFocus() and not ThePlayer.is_editing then
                    local wp = ThePlayer.replica.inventory and ThePlayer.replica.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)
                    if wp == nil or ( not wp.webbert_rt_panel ) then
                        if ThePlayer.HUD and ThePlayer.HUD.rt_panel and ThePlayer.HUD and ThePlayer.HUD.rt_panel.shown then
                            ThePlayer.HUD.rt_panel:ResetBtns()
                            ThePlayer.HUD.rt_panel:Hide()
                            return
                        end
                    end
                    if wp == nil or ( not wp.webbert_rt_panel ) then
                        -- 加入一个寻找手杖的功能, 只允许webbert用
                        if ThePlayer and ThePlayer.prefab == 'webbert' then
                            ThePlayer:PushEvent('webbert_find_staff_ininv')
                         end
                    end
                    if wp and wp.webbert_rt_panel and data_rt_panel[wp.webbert_rt_panel] and ThePlayer.HUD and ThePlayer.HUD.rt_panel then
                        if ThePlayer.HUD.rt_panel.shown then
                            ThePlayer.HUD.rt_panel:ResetBtns()
                            ThePlayer.HUD.rt_panel:Hide()
                        else
                            ThePlayer.HUD.rt_panel:ResetBtns()
                            ThePlayer.HUD.rt_panel:Show()
                            local data = data_rt_panel[wp.webbert_rt_panel]
                            for i = 1,8 do
                                ThePlayer.HUD.rt_panel:SetBtn(data.btns[i] and data.btns[i].name or '-',i,function ()
                                    if data.btns[i] and data.btns[i].on_click_fn_client then
                                        data.btns[i].on_click_fn_client()
                                    end
                                    data.when_any_btn_click_fn_client(i)
                                end,data.btns[i] and data.btns[i].hint or nil)
                            end
                        end
                    end
                end
            end)
        end
    end)
end)